/*******************************************************************************
* 
* Gloom game engine for FE r2
* 
* 
******************************************************************************/
#include "gloom.h"
#include "logging.h"
#include "process.h"
#include "loader.h"

#include <windows.h>
#ifdef _WIN64
#pragma comment (lib, "x64/dxguid.lib")
#else
#pragma comment (lib, "x86/dxguid.lib")
#endif

using namespace std;
using namespace noria::diagnostic;
#define FE_PE_NAME L"fe.exe"

namespace noria{ namespace engine
{

    GloomEngine::GloomEngine(void)
    {
        LOG_INFO("GloomEngine::ctor()");

        init();
    }

    GloomEngine::~GloomEngine(void)
    {
        // release manually...
        m_font.reset();
        m_graph.reset();
        m_audio.reset();
        m_locale.reset();
        m_res.reset();

        // uninitialize COM
        CoUninitialize();

        LOG_INFO("GloomEngine::~ctor()");
    }

    void GloomEngine::init()
    {
        // initialize COM for DirectX
        CoInitializeEx(NULL, COINIT_MULTITHREADED);

        // initilaize managers
        unique_ptr<LibraryLoader> loader;

        // resource manager
        {        
            HMODULE hMod;
            // determine the process name
            auto name = Process::getBaseName();

            if(name == FE_PE_NAME)
            {
                hMod = NULL;
            }
            else
            {
                hMod = LoadLibraryEx(FE_PE_NAME, NULL, LOAD_LIBRARY_AS_DATAFILE);
                if(!hMod)
                {
                    LOG_FATAL("Failure initializing ResourceManager: Failed to load module.");
                    goto end;
                }
            }

            m_res.reset(new ResourceManager(hMod));
        }

        // locale manager
        {
            // TODO:
        }

        // lib loader
        {
#if COM_MODE==1
#pragma message("#--COM_MODE is 1: Load XAudio by CLASSID.--#")
            loader.reset(new ComLoader());
#elif COM_MODE==2
#pragma message("#--COM_MODE is 2: Load XAudio isolated.--#")
            loader.reset(new IsolatedLoader());
#elif COM_MODE==3
#pragma message("#--COM_MODE is 3: Load XAudio from memory.--#")
            loader.reset(new MemoryLoader(m_res.get()));
#else
#error "COM_MODE is not specified."
#endif      
        }

        // audio manager
        {
            m_audio.reset(new FModManager(*loader.get()));
        }

        // graphic manager
        {
            // TODO:        
        }

        // font manager
        {
            // TODO:        
        }

        // exit
end:
        ;
    }

    //unique_ptr<GloomEngine> GloomEngine::s_instance;
    //// TODO: it is not thread safty, 
    //// NOTE: *DONOT* delete this pointer
    //GloomEngine* GloomEngine::instance()
    //{
    //    if(!s_instance)
    //    {
    //        s_instance.reset(new GloomEngine());
    //    }
    //    return s_instance.get();
    //}

    ResourceManager* GloomEngine::resource() const
    {
        return m_res.get();
    }

    FModManager* GloomEngine::audio() const
    {
        return m_audio.get();
    }

    GraphicManager* GloomEngine::graphic() const
    {
        return m_graph.get();
    }

    FontManager* GloomEngine::font() const
    {
        return m_font.get();
    }

    LocaleManager* GloomEngine::locale() const
    {
        return m_locale.get();
    }

}}